<template>
  <div class="virtualTable">
    <!--   show-header-overflow 会导致表头错开 || item.index == 0 ? !(assinObj['seePer'].includes(true)) : item.index >= 1 ? (!assinObj[`ohterPer${item.index}`].includes(true)) : !(assinObj['name'].includes(true)) -->
    <vxe-table
      :loading="loading"
      border="inner"
      show-overflow
      show-header-overflow
      ref="xTree"
      v-if="dataSource.length"
      :column-config="{ resizable: true }"
      :tree-config="{
        transform: true,
        rowField: 'id',
        parentField: 'parentId',
        expandAll: true,
      }"
      :row-config="{ isHover: true, height: 56 }"
      :data="dataSource"
      :max-height="props.height ? props.height : height"
      :scroll-y="{ gt: 20 }"
    >
      <vxe-column
        v-for="(item, index) in columns"
        :fixed="item.fixed == 'left' ? 'left' : null"
        :width="item.width"
        :min-width="item.minWidth"
        :tree-node="item.key == 'name'"
        :key="index"
      >
        <template #header="{ column, row, $index }">
          <div class="topLevel">
            <!--  -->
            <a-checkbox
              v-model:checked="item.selected"
              :key="item.index"
              @change="topSelect(item.index, item.selected)"
              :class="item.selectPAll.length == 2 ? 'halfSelect' : ''"
              :disabled="!props.isAssignable"
            >
              {{ item.title }}
            </a-checkbox>
          </div>
        </template>
        <template #default="{ row, column, $index }">
          <div v-if="item.dataIndex == 'name'" class="dataName">
            <!-- 栏目名称列 -->
            <!--  -->
            <a-checkbox
              v-model:checked="row.hasPerm"
              :class="row.allSelect.length == 2 ? 'halfSelect' : ''"
              @change="handleSiteNamePerm(item.index, row.id, row.hasPerm)"
              :disabled="!props.isAssignable || !row.assignable"
            >
              <div v-if="row.id == '-1'">
                {{ row.name }}
                <a-tooltip placement="right">
                  <template #title>
                    <span v-if="!props.isColumn"
                      >选中后，用户可拥有后续新增的站点权限</span
                    >
                    <span v-else>选中后，用户可拥有后续新增的栏目操作权限</span>
                  </template>
                  <i
                    class="iconfont icon-hint1"
                    style="
                      font-size: 16px;
                      margin-left: 8px;
                      color: rgba(0, 0, 0, 0.45);
                    "
                  >
                  </i>
                </a-tooltip>
              </div>
              <div v-else>{{ row.name }}</div>
            </a-checkbox>
          </div>
          <!-- 查看 新建 编辑。。列 -->
          <a-checkbox
            v-else
            v-model:checked="row.linePerms[item.index].hasPerm"
            :disabled="
              !props.isAssignable || !row.linePerms[item.index].assignable
            "
            @change="
              handleOtherPerm(
                item.index,
                row.id,
                row.linePerms[item.index].hasPerm
              )
            "
          >
          </a-checkbox>
          <!--  :disabled="!row.linePerms[column.index].assignable" -->
        </template>
      </vxe-column>
    </vxe-table>
    <vxe-table
      v-else
      :loading="loading"
      border="inner"
      show-overflow
      show-header-overflow
      ref="xTree"
      :column-config="{ resizable: true }"
      :tree-config="{
        transform: true,
        rowField: 'id',
        parentField: 'parentId',
        expandAll: true,
      }"
      :row-config="{ isHover: true, height: 56 }"
      :data="dataSource"
      max-height="580"
      :scroll-y="{ gt: 20 }"
    >
      <vxe-column
        v-for="(item, index) in columns"
        :fixed="item.fixed == 'left' ? 'left' : null"
        :width="item.width"
        :min-width="item.minWidth"
        :tree-node="item.key == 'name'"
        :key="index"
      >
        <template #header="{ column, row }">
          <div class="topLevel">
            <!-- @change="topSelect(item, row)" -->
            <a-checkbox
              v-model:checked="item.selected"
              :key="item.index"
              :class="item.className"
              :disabled="!props.isAssignable"
            >
              {{ item.title }}
            </a-checkbox>
          </div>
        </template>
      </vxe-column>
    </vxe-table>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, nextTick, watch, onMounted, computed } from "vue";
import { treeProps } from "./tableConfig/props";
import pagination from "@/components/pagination/index.vue";

// type
interface dataSourceType {
  [propName: string]: any;
}
// props
const props = defineProps({
  ...treeProps,
  isAssignable: {
    type: Boolean,
    default: true,
  },
});

//interface
interface DataList {
  [propName: string | number]: any;
}

//data
let dataSource = ref<DataList[]>([]);
const height = ref<number>(500);
const columns = ref(JSON.parse(JSON.stringify(props.columns)));

let firstTime = ref(true);
const loading = ref(true);

columns.value.forEach((item: DataList, index: number) => {
  item.selectPAll = [];
});
let idFloat = reactive<any>({});
let noParentData = reactive<any>({});
// watch
watch(
  () => props.columns,
  (newVal, oldVal) => {
    columns.value = JSON.parse(JSON.stringify(newVal));
  },
  { deep: true }
);
watch(
  () => props.dataSource,
  (newVal, oldVal) => {
    if (
      JSON.parse(JSON.stringify(newVal)) != JSON.parse(JSON.stringify(oldVal))
    ) {
      loading.value = true;
      dataSource.value = [];
      let originData: DataList[] = [];
      loopFloat(JSON.parse(JSON.stringify(newVal)), originData, []);
      nextTick(() => {
        dataSource.value = originData;
        topSelectAll(false);

        loading.value = false;
      });
      nextTick(() => {});
    }
  },
  { deep: true }
);
//onMounted
onMounted(() => {
  height.value = window.innerHeight - 390;
});

const topSelect = (index: number, isSelect: Boolean) => {
  // console.log(index, isSelect, "isSelect");
  oprateTop(index, isSelect);
};
const handleSiteNamePerm = (index: number, id: any, isSelect: Boolean) => {
  oprate1(index, id, isSelect);
};
const handleOtherPerm = (index: number, id: any, isSelect: Boolean) => {
  if (index > 0) {
    oprate2more(index, id, isSelect, null);
  } else if (index == 0) {
    oprate2(index, id, isSelect, null);
  }
};
const oprate2more = (
  index: number,
  id: any,
  isSelect: Boolean,
  noLoop: any
) => {
  idFloat[id].linePerms[index].hasPerm = isSelect;
  idFloat[id]["p" + index] = isSelect;
  //给了查看权限以外的权限，需要把本级查看权限放开
  let parentIds = idFloat[id].parentNodes || [];
  parentIds.push(id);
  if (isSelect && parentIds.length) {
    parentIds.forEach((item: any, index: number) => {
      // 给了查看权限以外的权限，需要把本级、父级及祖父级的查看权限放开
      idFloat[item].linePerms[0].hasPerm = true;
      idFloat[item]["p" + 0] = isSelect;
    });
  }
  parentIsSelectAll(parentIds, index, isSelect);
  if (!noLoop) {
    setTimeout(() => {
      checkTopSelect(isSelect);
    }, 40);
  }
};
const oprate2 = (index: number, id: any, isSelect: Boolean, noLoop: any) => {
  //此为查看权限
  let parentIds = idFloat[id].parentNodes || [];
  let childIds = idFloat[id].childNodes || [];
  childIds.push(id);
  parentIds.push(id);
  if (isSelect && parentIds.length) {
    parentIds.concat(childIds).forEach((item: any, index: number) => {
      // 给了查看权限，需要把本级、父级及祖父级、子级及孙子级的查看权限放开
      idFloat[item].linePerms[0].hasPerm = isSelect;
      idFloat[item]["p" + 0] = isSelect;
    });
  }
  if (!isSelect && childIds) {
    // 取消给了查看权限需要把本级及所有子级的查看、新建、编辑等权限取消
    let len = columns.value.length;
    childIds.forEach((item: any, index: any) => {
      for (let i = 0; i < len - 1; i++) {
        idFloat[item].linePerms[i].hasPerm = isSelect;
        idFloat[item]["p" + i] = isSelect;
      }
    });
  }
  parentIsSelectAll(parentIds.concat(childIds), index, isSelect);
  if (!noLoop) {
    setTimeout(() => {
      checkTopSelect(isSelect);
    }, 40);
  }
};
const oprate1 = (index: number, id: any, isSelect: Boolean) => {
  //此为该栏目所有权限
  let parentIds = idFloat[id].parentNodes || [];
  let childIds = idFloat[id].childNodes || [];
  childIds.push(id);
  parentIds.push(id);
  // 全选本级子级所有权限， 以及所有父级的查看权限
  let len = columns.value.length;
  childIds.forEach((item: any, index: number) => {
    for (let i = 0; i < len - 1; i++) {
      idFloat[item].linePerms[i].hasPerm = isSelect;
      idFloat[item]["p" + i] = isSelect;
    }
    idFloat[item].allSelect = isSelect ? [true] : [false];
    idFloat[item].hasPerm = isSelect ? true : false;
  });
  if (isSelect && parentIds) {
    // 如果是选中，则把其父级及祖父级的查看要选上
    parentIds.forEach((item: any, index: number) => {
      // 给了查看权限，需要把本级、父级及祖父级的查看权限放开
      idFloat[item].linePerms[0].hasPerm = isSelect;
      idFloat[item]["p" + 0] = isSelect;
    });
  }
  setTimeout(() => {
    checkTopSelect(isSelect);
  }, 40);
};
const oprateTop = (idx: number, isSelect: any) => {
  if (idx == 0) {
    // 操作的是查看的
    for (let i in noParentData) {
      oprate2(idx, i, isSelect, "noLoop");
    }
    setTimeout(() => {
      checkTopSelect(isSelect);
    }, 40);
  } else if (idx > 0) {
    for (let i in idFloat) {
      oprate2more(idx, i, isSelect, "noLoop");
    }
    setTimeout(() => {
      checkTopSelect(isSelect);
    }, 40);
  } else if (idx == -1) {
    for (let i in idFloat) {
      idFloat[i].linePerms.forEach((item: any, index: number) => {
        item.hasPerm = isSelect;
        idFloat[i]["p" + index] = isSelect;
      });
    }
    for (let i in noParentData) {
      oprate2(idx, i, isSelect, "noLoop");
    }
    setTimeout(() => {
      checkTopSelect(isSelect);
    }, 10);
  }
};
const parentIsSelectAll = (ids: any[], index: number, isSelect: Boolean) => {
  let parentIds = [...new Set(ids)]; // 所有父级的
  let len = columns.value.length;
  parentIds.reverse().forEach((item: any, index: number) => {
    let childIds = idFloat[item].childNodes;
    let allSelect: any = [];
    [...childIds, item].forEach((citem, index) => {
      allSelect = [
        ...new Set(
          allSelect.concat(
            idFloat[citem].linePerms.map((pItem: any) => pItem.hasPerm)
          )
        ),
      ];
    });
    idFloat[item].allSelect = allSelect;
    idFloat[item].hasPerm =
      allSelect.length == 1 && allSelect[0] == true ? true : false;
  });
};

// loopFloat 扁平化站群、菜单数据, vxeTable只识别扁平化数据
const loopFloat = (
  data: dataSourceType[],
  list: dataSourceType[],
  pid: (string | number | any)[]
) => {
  data.forEach((item: dataSourceType) => {
    item.parentNodes = JSON.parse(JSON.stringify(pid));
    item.allSelect = [...new Set(item.linePerms.map((pItem: any) => pItem.hasPerm))];
    if (item.parentId) {
      item.parentNodes.push(item.parentId);
    }
    item.childNodes = [];
    if (item.children instanceof Array && item.children.length) {
      getChildIds(item.children, item.childNodes, item.allSelect);
    }
    item.linePerms.forEach((pItem: any, index: number) => {
      columns.value[index + 1].selectPAll = [
        ...new Set([...columns.value[index + 1].selectPAll, pItem.hasPerm]),
      ];
    });
    item.linePerms.forEach((pitem: any, index: number) => {
      item["p" + index] = pitem.hasPerm;
    });
    let obj = {
      ...item,
      id: item.id,
      name: item.name,
      parentId: item.parentId,
      linePerms: item.linePerms,
      parentNodes: item.parentNodes,
      childNodes: item.childNodes,
      assignable: item.assignable,
      allSelect: item.allSelect,
      hasPerm:
        item.allSelect.length == 1 && item.allSelect[0] == true ? true : false,
    };

    list.push(obj);
    idFloat[item.id] = obj;
    if (!item.parentId) {
      noParentData[item.id] = obj;
    }
    item.children && item.children.length
      ? loopFloat(
          item.children,
          list,
          JSON.parse(JSON.stringify(item.parentNodes))
        )
      : "";
  });
};
const topSelectAll = (isSelect: Boolean) => {
  let arr: any = [];
  columns.value.forEach((item: any, index: number) => {
    if (index > 0) {
      item.selected =
        item.selectPAll.length == 1 && item.selectPAll[0] == true
          ? true
          : false;
      !arr.includes(item.selected) ? arr.push(item.selected) : "";
    }
  });
  columns.value[0].selectPAll = arr;

  if (isSelect) {
    !columns.value[0].selectPAll.includes(isSelect)
      ? columns.value[0].selectPAll.push(isSelect)
      : "";
  }
  if (columns.value[1].selectPAll.length > 1) {
    columns.value[0].selectPAll = columns.value[1].selectPAll;
  }
  columns.value[0].selected =
    columns.value[0].selectPAll.length == 1 && arr[0] == true ? true : false;
};
const checkTopSelect = (isSelect: Boolean) => {
  columns.value.forEach((item: any) => {
    item.selectPAll = [];
  });

  for (let i in idFloat) {
    for (let j = 1; j < columns.value.length; j++) {
      !columns.value[j].selectPAll.includes(idFloat[i][`p${j - 1}`])
        ? columns.value[j].selectPAll.push(idFloat[i][`p${j - 1}`])
        : "";
    }
  }
  // console.log(columns.value, " columns.value columns.value");
  setTimeout(() => {
    topSelectAll(isSelect);
  }, 10);
};
const getChildIds = (
  data: DataList[],
  list: (string | number)[],
  allSelect: (string | number)[]
) => {
  data.forEach((item: DataList) => {
    list.push(item.id);
    allSelect = [
      ...new Set(
        allSelect.concat(item.linePerms.map((pItem: any) => pItem.hasPerm))
      ),
    ];
    item.linePerms.forEach((pItem: any, index: number) => {
      columns.value[index + 1].selectPAll = [
        ...new Set([...columns.value[index + 1].selectPAll, pItem.hasPerm]),
      ];
    });
    if (item.children instanceof Array && item.children.length) {
      getChildIds(item.children, list, allSelect);
    }
  });
};
//defineExpose
defineExpose({ dataSource });
</script>
<style lang="less" scoped></style>
<style lang="less">
.virtualTable {
  padding-top: 24px;
  min-height: 200px;

  .vxe-table--fixed-left-wrapper {
    height: 100% !important;
    z-index: 2;
    background: #f7f7f7;

    .vxe-table--body-wrapper.fixed-left--wrapper {
      overflow-x: auto !important;
      min-height: calc(100% - 56px);
    }
  }

  // .fixed-left--wrapper {
  //   min-width: 400px;
  // }

  .vxe-table--body {
    min-width: 1200px;
  }
}

.topLevel,
.dataName {
  .halfSelect {
    .ant-checkbox-inner {
      background: #fff;
      border-color: var(--theme_button_bg_color, #1f6ded);
    }

    .ant-checkbox-inner::after {
      position: absolute;
      display: table;
      border: 2px solid var(--theme_button_bg_color, #1f6ded);
      border-top: 0;
      border-left: 0;
      transform: rotate(90deg) scale(1) translate(-118%, -15%);
      opacity: 1;
      transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
      content: " ";
      border-bottom: 0;
    }
  }

  .halfSelect {
    .ant-checkbox-disabled {
      .ant-checkbox-inner {
        background: #f5f5f5;
        border-color: #d9d9d9;
      }

      .ant-checkbox-inner::after {
        position: absolute;
        display: table;
        border: 2px solid rgba(0, 0, 0, 0.25);
        border-top: 0;
        border-left: 0;
        transform: rotate(90deg) scale(1) translate(-118%, -15%);
        opacity: 1;
        transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
        content: " ";
        border-bottom: 0;
      }
    }
  }

  .selected {
    .ant-checkbox-inner {
      background: var(--theme_button_bg_color, #1f6ded);
      border-color: var(--theme_button_bg_color, #1f6ded);
    }

    .ant-checkbox-inner::after {
      position: absolute;
      display: table;
      border: 2px solid #fff;
      border-top: 0;
      border-left: 0;
      transform: rotate(45deg) scale(1) translate(-50%, -50%);
      opacity: 1;
      transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
      content: " ";
    }
  }

  .noSelected {
    .ant-checkbox-checked .ant-checkbox-inner::after {
      position: absolute;
      display: table;
      border: 2px solid #fff;
      border-top: 0;
      border-left: 0;
      transform: rotate(45deg) scale(1) translate(-50%, -50%);
      opacity: 0;
      transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
      content: " ";
    }

    .ant-checkbox-checked .ant-checkbox-inner {
      background: #fff;
      border-color: 1px solid #d9d9d9;
    }
  }
}

.permissionTable {
  background-color: inherit;

  ::deep(th:nth-child(1)) {
    padding-left: 16px;
  }
}

.rotate90 {
  transform: scale(0.8) rotate(90deg) !important;
}
</style>
